{
 "cells": [
  {
   "cell_type": "raw",
   "id": "fe63ffaf",
   "metadata": {},
   "source": [
    "---\n",
    "keywords: [RunnableBinding, LCEL]\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "711752cb-4f15-42a3-9838-a0c67f397771",
   "metadata": {},
   "source": [
    "# How to attach runtime arguments to a Runnable\n",
    "\n",
    ":::info Prerequisites\n",
    "\n",
    "This guide assumes familiarity with the following concepts:\n",
    "\n",
    "- [LangChain Expression Language (LCEL)](/docs/concepts/#langchain-expression-language)\n",
    "- [Chaining runnables](/docs/how_to/sequence/)\n",
    "- [Tool calling](/docs/how_to/tool_calling/)\n",
    "\n",
    ":::\n",
    "\n",
    "Sometimes we want to invoke a [`Runnable`](https://v02.api.js.langchain.com/classes/langchain_core_runnables.Runnable.html) within a [RunnableSequence](https://v02.api.js.langchain.com/classes/langchain_core_runnables.RunnableSequence.html) with constant arguments that are not part of the output of the preceding Runnable in the sequence, and which are not part of the user input. We can use the [`Runnable.bind()`](https://v02.api.js.langchain.com/classes/langchain_core_runnables.Runnable.html#bind) method to set these arguments ahead of time.\n",
    "\n",
    "## Binding stop sequences\n",
    "\n",
    "Suppose we have a simple prompt + model chain:\n",
    "\n",
    "```{=mdx}\n",
    "import IntegrationInstallTooltip from \"@mdx_components/integration_install_tooltip.mdx\";\n",
    "import Npm2Yarn from \"@theme/Npm2Yarn\";\n",
    "\n",
    "<IntegrationInstallTooltip></IntegrationInstallTooltip>\n",
    "\n",
    "<Npm2Yarn>\n",
    "  @langchain/openai\n",
    "</Npm2Yarn>\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f3fdf86d-155f-4587-b7cd-52d363970c1d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "EQUATION: x^3 + 7 = 12\n",
      "\n",
      "SOLUTION: \n",
      "Subtract 7 from both sides:\n",
      "x^3 = 5\n",
      "\n",
      "Take the cube root of both sides:\n",
      "x = ∛5\n"
     ]
    }
   ],
   "source": [
    "import { StringOutputParser } from \"@langchain/core/output_parsers\";\n",
    "import { ChatPromptTemplate } from \"@langchain/core/prompts\";\n",
    "import { ChatOpenAI } from \"@langchain/openai\";\n",
    "\n",
    "const prompt = ChatPromptTemplate.fromMessages(\n",
    "    [\n",
    "        [\n",
    "            \"system\",\n",
    "            \"Write out the following equation using algebraic symbols then solve it. Use the format\\n\\nEQUATION:...\\nSOLUTION:...\\n\\n\",\n",
    "        ],\n",
    "        [\"human\", \"{equation_statement}\"],\n",
    "    ]\n",
    ")\n",
    "\n",
    "const model = new ChatOpenAI({ temperature: 0 });\n",
    "\n",
    "const runnable = prompt.pipe(model).pipe(new StringOutputParser());\n",
    "\n",
    "const res = await runnable.invoke({\n",
    "  equation_statement: \"x raised to the third plus seven equals 12\"\n",
    "});\n",
    "\n",
    "console.log(res);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "929c9aba-a4a0-462c-adac-2cfc2156e117",
   "metadata": {},
   "source": [
    "and want to call the model with certain `stop` words so that we shorten the output, which is useful in certain types of prompting techniques. While we can pass some arguments into the constructor, other runtime args use the `.bind()` method as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "32e0484a-78c5-4570-a00b-20d597245a96",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "EQUATION: x^3 + 7 = 12\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "const runnable = prompt\n",
    "  .pipe(model.bind({ stop: \"SOLUTION\" }))\n",
    "  .pipe(new StringOutputParser());\n",
    "\n",
    "const res = await runnable.invoke({\n",
    "  equation_statement: \"x raised to the third plus seven equals 12\"\n",
    "});\n",
    "\n",
    "console.log(res);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f07d7528-9269-4d6f-b12e-3669592a9e03",
   "metadata": {},
   "source": [
    "What you can bind to a Runnable will depend on the extra parameters you can pass when invoking it.\n",
    "\n",
    "## Attaching OpenAI tools\n",
    "\n",
    "Another common use-case is tool calling. While you should generally use the [`.bind_tools()`](/docs/how_to/tool_calling/) method for tool-calling models, you can also bind provider-specific args directly if you want lower level control:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2cdeeb4c-0c1f-43da-bd58-4f591d9e0671",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage {\n",
       "  lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "  lc_kwargs: {\n",
       "    content: \u001b[32m\"\"\u001b[39m,\n",
       "    tool_calls: [\n",
       "      {\n",
       "        name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "        args: { location: \u001b[32m\"San Francisco, CA\"\u001b[39m },\n",
       "        id: \u001b[32m\"call_iDKz4zU8PKBaaIT052fJkMMF\"\u001b[39m\n",
       "      },\n",
       "      {\n",
       "        name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "        args: { location: \u001b[32m\"New York, NY\"\u001b[39m },\n",
       "        id: \u001b[32m\"call_niQwZDOqO6OJTBiDBFG8FODc\"\u001b[39m\n",
       "      },\n",
       "      {\n",
       "        name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "        args: { location: \u001b[32m\"Los Angeles, CA\"\u001b[39m },\n",
       "        id: \u001b[32m\"call_zLXH2cDVQy0nAVC0ViWuEP4m\"\u001b[39m\n",
       "      }\n",
       "    ],\n",
       "    invalid_tool_calls: [],\n",
       "    additional_kwargs: {\n",
       "      function_call: \u001b[90mundefined\u001b[39m,\n",
       "      tool_calls: [\n",
       "        {\n",
       "          id: \u001b[32m\"call_iDKz4zU8PKBaaIT052fJkMMF\"\u001b[39m,\n",
       "          type: \u001b[32m\"function\"\u001b[39m,\n",
       "          function: \u001b[36m[Object]\u001b[39m\n",
       "        },\n",
       "        {\n",
       "          id: \u001b[32m\"call_niQwZDOqO6OJTBiDBFG8FODc\"\u001b[39m,\n",
       "          type: \u001b[32m\"function\"\u001b[39m,\n",
       "          function: \u001b[36m[Object]\u001b[39m\n",
       "        },\n",
       "        {\n",
       "          id: \u001b[32m\"call_zLXH2cDVQy0nAVC0ViWuEP4m\"\u001b[39m,\n",
       "          type: \u001b[32m\"function\"\u001b[39m,\n",
       "          function: \u001b[36m[Object]\u001b[39m\n",
       "        }\n",
       "      ]\n",
       "    },\n",
       "    response_metadata: {}\n",
       "  },\n",
       "  lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "  content: \u001b[32m\"\"\u001b[39m,\n",
       "  name: \u001b[90mundefined\u001b[39m,\n",
       "  additional_kwargs: {\n",
       "    function_call: \u001b[90mundefined\u001b[39m,\n",
       "    tool_calls: [\n",
       "      {\n",
       "        id: \u001b[32m\"call_iDKz4zU8PKBaaIT052fJkMMF\"\u001b[39m,\n",
       "        type: \u001b[32m\"function\"\u001b[39m,\n",
       "        function: {\n",
       "          name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "          arguments: \u001b[32m'{\"location\": \"San Francisco, CA\"}'\u001b[39m\n",
       "        }\n",
       "      },\n",
       "      {\n",
       "        id: \u001b[32m\"call_niQwZDOqO6OJTBiDBFG8FODc\"\u001b[39m,\n",
       "        type: \u001b[32m\"function\"\u001b[39m,\n",
       "        function: {\n",
       "          name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "          arguments: \u001b[32m'{\"location\": \"New York, NY\"}'\u001b[39m\n",
       "        }\n",
       "      },\n",
       "      {\n",
       "        id: \u001b[32m\"call_zLXH2cDVQy0nAVC0ViWuEP4m\"\u001b[39m,\n",
       "        type: \u001b[32m\"function\"\u001b[39m,\n",
       "        function: {\n",
       "          name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "          arguments: \u001b[32m'{\"location\": \"Los Angeles, CA\"}'\u001b[39m\n",
       "        }\n",
       "      }\n",
       "    ]\n",
       "  },\n",
       "  response_metadata: {\n",
       "    tokenUsage: { completionTokens: \u001b[33m70\u001b[39m, promptTokens: \u001b[33m82\u001b[39m, totalTokens: \u001b[33m152\u001b[39m },\n",
       "    finish_reason: \u001b[32m\"tool_calls\"\u001b[39m\n",
       "  },\n",
       "  tool_calls: [\n",
       "    {\n",
       "      name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "      args: { location: \u001b[32m\"San Francisco, CA\"\u001b[39m },\n",
       "      id: \u001b[32m\"call_iDKz4zU8PKBaaIT052fJkMMF\"\u001b[39m\n",
       "    },\n",
       "    {\n",
       "      name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "      args: { location: \u001b[32m\"New York, NY\"\u001b[39m },\n",
       "      id: \u001b[32m\"call_niQwZDOqO6OJTBiDBFG8FODc\"\u001b[39m\n",
       "    },\n",
       "    {\n",
       "      name: \u001b[32m\"get_current_weather\"\u001b[39m,\n",
       "      args: { location: \u001b[32m\"Los Angeles, CA\"\u001b[39m },\n",
       "      id: \u001b[32m\"call_zLXH2cDVQy0nAVC0ViWuEP4m\"\u001b[39m\n",
       "    }\n",
       "  ],\n",
       "  invalid_tool_calls: []\n",
       "}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "const tools = [\n",
    "  {\n",
    "    \"type\": \"function\",\n",
    "    \"function\": {\n",
    "      \"name\": \"get_current_weather\",\n",
    "      \"description\": \"Get the current weather in a given location\",\n",
    "      \"parameters\": {\n",
    "        \"type\": \"object\",\n",
    "        \"properties\": {\n",
    "          \"location\": {\n",
    "            \"type\": \"string\",\n",
    "            \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
    "          },\n",
    "          \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n",
    "        },\n",
    "        \"required\": [\"location\"],\n",
    "      },\n",
    "    },\n",
    "  }\n",
    "];\n",
    "\n",
    "const model = new ChatOpenAI({ model: \"gpt-4o\" }).bind({ tools });\n",
    "\n",
    "await model.invoke(\"What's the weather in SF, NYC and LA?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "095001f7",
   "metadata": {},
   "source": [
    "## Next steps\n",
    "\n",
    "You now know how to bind runtime arguments to a Runnable.\n",
    "\n",
    "Next, you might be interested in our how-to guides on [passing data through a chain](/docs/how_to/passthrough/)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Deno",
   "language": "typescript",
   "name": "deno"
  },
  "language_info": {
   "file_extension": ".ts",
   "mimetype": "text/x.typescript",
   "name": "typescript",
   "nb_converter": "script",
   "pygments_lexer": "typescript",
   "version": "5.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
